package bj.gui

import scala.swing.event
import event.ButtonClicked
import scala.swing.SimpleGUIApplication
import scala.swing.MainFrame
import scala.swing.Label
import scala.swing.Swing
import scala.swing.Button
import scala.swing.FlowPanel
import scala.swing.BorderPanel
import scala.swing.BoxPanel
import scala.swing.Orientation
import scala.swing.Table
import scala.swing.ScrollPane
import scala.swing.MenuBar
import scala.swing.Menu
import scala.swing.MenuItem
import scala.swing.Action
import java.awt.Dimension
import javax.swing.ImageIcon
import scala.swing.event.TableRowsSelected
import javax.swing.table.DefaultTableModel
import org.apache.log4j.PropertyConfigurator
import bj.util.Logs
import org.apache.log4j.Logger
import org.apache.log4j.Level
import bj.actor.Player
import bj.actor.House
import bj.actor.Dealer
import scala.actors.Actor
import bj.actor.Go
import bj.actor.Stop
import bj.util.Logs
import bj.Config
import bj.actor.SendMsg
import bj.actor.GetTables
import bj.actor.SendTables
import bj.actor.SendTotalEarnings
import bj.actor.RemoveTable
import bj.actor.AddTable
import bj.actor.EdTable
import bj.actor.TestMessage
import bj.actor.Send
import bj.actor.Receive
import bj.actor.Intermediator

object EyeInTheSky extends SimpleGUIApplication with Logs {
  javax.swing.UIManager.setLookAndFeel(Constants.LF)
  PropertyConfigurator.configure("log4j.properties")

    // Listen to the house so I can process events received from it
    implicit val intermediator = Intermediator(House)
    
  def top = mainFrame
  val mainFrame = new MainFrame {
    title = "Blackjack - Eye In The Sky View"
    minimumSize = Constants.lobbySize

    menuBar = new MenuBar {
      contents += new Menu("File") {
        contents += new MenuItem(Action("Exit") {
          System.exit(0);
        })
      }
      contents += new Menu("Help") {
        contents += new MenuItem(Action("Help") {
          new BjInfoBox(new Label("Coming soon!"))
        })
        contents += new MenuItem(Action("About") {
          new BjInfoBox(new Label("<html>Alpha version<br>Copyright 2011<br>Scott Sigalas<br>Anna Clayton</html>"))
        })
      }
    }

    val earningsLabel = new Label {
      text = " "
    }

    val startHouseButton = new Button { text = "Start House" }
    val stopHouseButton = new Button {
      text = "Stop House"
      enabled = false
    }
    val createTableButton = new Button {
      text = "Create Table"
      enabled = false
    }
    val stopTableButton = new Button {
      text = "Stop Table"
      enabled = false
    }
    val editTableButton = new Button {
      text = "Edit Table"
      enabled = false
    }
    val viewPlayersButton = new Button {
      text = "View Players"
      enabled = false
    }
    val refreshButton = new Button {
      text = "Refresh"
      enabled = false
    }

      var tableData : Array[Array[AnyRef]] = new Array(0);
      
      val headers = Array("Table #", "Minimum Bet", "Maximum Bet", "Players", "Dealer", "Earnings/Losses")
    
    val tableModel = new DefaultTableModel(
     tableData.asInstanceOf[Array[Array[Object]]], // Data
     headers.asInstanceOf[Array[Object]]) // Column names
    val tablesTable = new Table(tableData.size, headers.size) {model = tableModel
      showGrid = true
      gridColor = Constants.gridColor
      border = Swing.EmptyBorder(20)
      visible = false}


    val topPanel = new BorderPanel() {
      add(new Label {
        icon = new ImageIcon("images/BJLogo2.gif")
      }, BorderPanel.Position.West)
      add(new Label { text = "Eye In The Sky" }, BorderPanel.Position.Center)
      add(earningsLabel, BorderPanel.Position.East)
      border = Swing.EmptyBorder(0, 0, 0, 10)
      background = Constants.greenBack
    }
    val midPanel = new FlowPanel() {
      contents +=
        new ScrollPane {
          viewportView = tablesTable
          preferredSize = new Dimension(600, 110)
        }
      background = Constants.greenBack
    }

    val buttonRow1 = new FlowPanel() {
      contents += startHouseButton
      contents += createTableButton
      contents += editTableButton
      contents += refreshButton
      background = Constants.greenBack
    }
    val buttonRow2 = new FlowPanel() {
      contents += stopHouseButton
      contents += stopTableButton
      contents += viewPlayersButton
      background = Constants.greenBack
    }
    val buttonPanel = new BoxPanel(Orientation.Vertical) {
      contents += buttonRow1
      contents += buttonRow2
      background = Constants.greenBack
    }

    contents = new BorderPanel() {
      add(topPanel, BorderPanel.Position.North)
      add(midPanel, BorderPanel.Position.Center)
      add(buttonPanel, BorderPanel.Position.South)
      border = Swing.EmptyBorder(10)
      background = Constants.greenBack
    }

    
    listenTo(intermediator)
    listenTo(createTableButton)
    listenTo(stopTableButton)
    listenTo(startHouseButton)
    listenTo(stopHouseButton)
    listenTo(editTableButton)
    listenTo(viewPlayersButton)
    listenTo(refreshButton)
    listenTo(tablesTable.selection)
    reactions += {
      case ButtonClicked(`createTableButton`) =>
      	clickCreateTable()
      case ButtonClicked(`stopTableButton`) =>
      	clickStopTable()
      case ButtonClicked(`refreshButton`) =>
        clickRefresh()
      case ButtonClicked(`editTableButton`) =>
        clickEditTable()
      case ButtonClicked(`viewPlayersButton`) =>
        println("Clicked viewPlayers button")
        new Players()
      case ButtonClicked(`startHouseButton`) =>
        clickStart()
      case ButtonClicked(`stopHouseButton`) =>
        clickStop()
      case TableRowsSelected(`tablesTable`, range, adjusting) =>
        editTableButton.enabled = true
        stopTableButton.enabled = true
      // Receive events come from the House
      // Receive an informational message from the house. Display an informational message with the text
      case Receive(SendMsg(message)) => new BjInfoBox(new Label { text = message }) 
      // Receive a response to GetTables. The value received is an Array of Arrays used to populate the table
      case Receive(SendTables(tables)) => refreshTable(tables)
      // Receive the total earnings for the house and update the label at the top of the screen
      case Receive(SendTotalEarnings(value)) => 
      	earningsLabel.text = "House earnings/losses: $" + String.format("%3.2f", double2Double(value))
    }
    debug("starting the house")
    House.start    
  }
  
  // createTable button has been clicked: open a new window to specify table parameters
  def clickCreateTable(): Unit = {
    println("Clicked createTable button")
    new CreateTable()
  }
  
  // editTable button has been clicked: open a new window to edit the table and populate it with the table's current info (from the tablesTable)
  def clickEditTable(): Unit = {
    println("Clicked editTable button")
    if (mainFrame.tablesTable.selection.rows.size > 1)
      new BjInfoBox(new Label("Please select only one table"))
    else
      new EditTable(
    		  	mainFrame.tableModel.getValueAt(mainFrame.tablesTable.selection.rows.first,0).toString,
    		  	mainFrame.tableModel.getValueAt(mainFrame.tablesTable.selection.rows.first,1).toString().toDouble,
    		  	mainFrame.tableModel.getValueAt(mainFrame.tablesTable.selection.rows.first,2).toString().toDouble,
    		  	mainFrame.tableModel.getValueAt(mainFrame.tablesTable.selection.rows.first,4).toString
      )
  }

  // stopTable has been clicked: send a message to the house to remove each affected table
  def clickStopTable(): Unit = {
    println("Clicked stopTable button")
    mainFrame.tablesTable.selection.rows.foreach(x => Send(RemoveTable(mainFrame.tableModel.getValueAt(x, 0).toString().toInt)))
    mainFrame.stopTableButton.enabled = false
    mainFrame.editTableButton.enabled = false
  }

  // startHouse has been clicked: enable GUI buttons, send a GetTables request to the House, send the Go command to the house
  def clickStart() : Unit = {
    println("Clicked startHouse button")
    mainFrame.startHouseButton.enabled = false
    mainFrame.createTableButton.enabled = true
    mainFrame.refreshButton.enabled = true
    mainFrame.viewPlayersButton.enabled = true
    mainFrame.stopHouseButton.enabled = true
    House ! Go
    Send(GetTables)
    mainFrame.tablesTable.visible = true
  }
  
  // An updated array of table data has been received from the house.  
  // Remove all current rows from the tables table and add new rows based on the data received
  def refreshTable(value: Array[Array[AnyRef]]): Unit = {
    println("Refreshing Eye In The Sky Table data")
    mainFrame.tableData.foreach(t => mainFrame.tableModel.removeRow(0))
    mainFrame.tableData = value
    mainFrame.tableData.foreach(t => mainFrame.tableModel.addRow(t))
  }
  
  // stopHouse has been clicked: send the house a Stop message and disable GUI buttons
  def clickStop() : Unit = {
		println("Clicked stopHouse button")
    	House ! Stop
        mainFrame.tablesTable.visible = false
        mainFrame.stopHouseButton.enabled = false
        mainFrame.startHouseButton.enabled = true
        mainFrame.createTableButton.enabled = false
        mainFrame.editTableButton.enabled = false
        mainFrame.stopTableButton.enabled = false
        mainFrame.refreshButton.enabled = false
        mainFrame.viewPlayersButton.enabled = false
  }
  
  // The Refresh button has been clicked: send the house a GetTables request
  def clickRefresh(): Unit = {
    println("Clicked refresh button")
    Send(GetTables)
    mainFrame.tablesTable.selection.rows.clear
    mainFrame.editTableButton.enabled = false
    mainFrame.stopTableButton.enabled = false
  }
  
  // Send a message to the House
  def sendMsg(event : Any) : Unit = {
    debug("Eye In The Sky is sending "+event.toString)
    Send(event)
  }
}